#include <sys/types.h>
#include <stdarg.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <asm/segment.h>
#include <linux/sched.h>

#define set_bit(bitnr,addr) ({ \
register int __res ; \
__asm__("bt %2,%3;setb %%al":"=a" (__res):"a" (0),"r" (bitnr),"m" (*(addr))); \
__res; })

int sprintf(char *buf, const char *fmt, ...);

int read_proc(int dev, char *buf, int count, off_t * pos)
{
    // psinfo 文件
    if (dev == 0)
    {
        char *data = malloc(count);
        char *tail = data;
        int size = 0;
        sprintf(data, "pid\tstate\tfather\tcounter\tstart_time\n\0");
        while (*tail!='\0')
        {
            tail++;
            size++;
        }
        

        struct task_struct **p; 
        for(p = &LAST_TASK ; p > &FIRST_TASK ; --p) 
        {
            if (*p)
            {
                sprintf(tail, "%ld\t%ld\t%ld\t%ld\t%ld\n\0", (*p)->pid, (*p)->state, (*p)->father, (*p)->start_time);
                while (*tail!='\0')
                {
                    tail++;
                    size++;
                }
            }
        }
        *tail = '\0';

        // 如果已经读完了，直接退出
        if (*pos >= size) 
        {
            return 0;
        }
        // 如果没读完，从断掉的地方继续
        else
        {
            int tmp = *pos;
            while (tmp-->0)
            {
                data++;
            }
            
        }

        int tmp_count = 0;
        while (*data!='\0' && tmp_count <= count)
        {
            put_fs_byte(*(data++), buf++);
            tmp_count++;
            (*pos)++;
        }
        
        return tmp_count;
    }
    // hdinfo 文件
    else if (dev == 1)
    {
        char *data = malloc(count);
        char *tail = data;
        int size = 0;

        struct super_block * sb;
        sb = get_super(current->root->i_dev);

        struct buffer_head * bh;
        int total_blocks = sb->s_nzones;
        int free_blocks = 0;

        int i = total_blocks;
        while (-- i >= 0)
		    if (!set_bit(i&8191,sb->s_zmap[i>>13]->b_data))
			    free_blocks++;

        sprintf(data, "total_blocks:\t%d\nfree_blocks:\t%d\nused_blocks:\t%d\n", total_blocks, free_blocks, total_blocks-free_blocks);
        while (*tail!='\0')
        {
            tail++;
            size++;
        }

        if (*pos >= size)
        {
            return 0;
        }

        // 输出
        int tmp_count = 0;
        while (*data!='\0' && tmp_count <= count)
        {
            put_fs_byte(*(data++), buf++);
            tmp_count++;
            (*pos)++;
        }
        return tmp_count;
    }
}

int sprintf(char *buf, const char *fmt, ...)
{
    va_list args; int i;
    va_start(args, fmt);
    i=vsprintf(buf, fmt, args);
    va_end(args);
    return i;
}